/*
 * ConditionalExpressionAst.cpp
 *
 *  Created on: 12 Nov 2010
 *      Author: kn308
 */

#include "ConditionalExpressionAst.h"
#include <MAlice/Ast/IntegerLiteralAst.h>
#include <MAlice/Ast/CastBooleanAst.h>

namespace MAlice
{
ConditionalExpressionAst::ConditionalExpressionAst(ExpressionAst* cond, Ast* body) :
	mCond(cond), mBody(body), mLast(false)
{
}

ConditionalExpressionAst::~ConditionalExpressionAst()
{
	delete mCond;
	delete mBody;
}

Value* ConditionalExpressionAst::generate()
{
	assert(mMerge && "NullPointer");

	Codegen* g = Codegen::get();
	Builder* builder = g->getBuilder();

	Function *F = builder->GetInsertBlock()->getParent();

	if(mLast)
	{
		// Create blocks for the then and else cases.  Insert the 'then' block at the
		// end of the function.
		BasicBlock *thenBB = BasicBlock::Create(g->getContext(), "if.then", F);

		Value *condition = CastBooleanAst(mCond).generate();
		builder->CreateCondBr(condition, thenBB, mMerge);

		// assume jumped to then
		builder->SetInsertPoint(thenBB);
		mBody->generate();

		// jump to merge if its not a return instruction
		if (!isa<ReturnInst> (&*builder->GetInsertPoint()))
			builder->CreateBr(mMerge);

		// assume jumped to else
		builder->SetInsertPoint(mMerge);
	}
	else
	{
		// Create blocks for the then and else cases.  Insert the 'then' block at the
		// end of the function.
		BasicBlock *elseBB = BasicBlock::Create(g->getContext(), "if.else", F);
		BasicBlock *thenBB = BasicBlock::Create(g->getContext(), "if.then", F, elseBB);

		Value *condition = CastBooleanAst(mCond).generate();
		builder->CreateCondBr(condition, thenBB, elseBB);

		// assume jumped to then
		builder->SetInsertPoint(thenBB);

		mBody->generate();

		// jump to merge if its not a return instruction
		if (!isa<ReturnInst> (&*builder->GetInsertPoint()))
			builder->CreateBr(mMerge);

		// assume jumped to else
		builder->SetInsertPoint(elseBB);
	}

	return F;
}

UnConditionalExpressionAst::UnConditionalExpressionAst(Ast* stmt) :
	ConditionalExpressionAst(NULL, stmt)
{
}

UnConditionalExpressionAst::~UnConditionalExpressionAst()
{
	delete mCond;
	delete mBody;
}

Value* UnConditionalExpressionAst::generate()
{
	assert(mMerge && "NullPointer");
	assert(!mCond && "Not NullPointer");

	Codegen*  g = Codegen::get();
	Builder*  builder = g->getBuilder();
	Function* F = builder->GetInsertBlock()->getParent();

	mBody->generate();

	// jump to merge if its not a return instruction
	if (!isa<ReturnInst> (&*builder->GetInsertPoint()))
		builder->CreateBr(mMerge);

	// assume jumped to merge
	builder->SetInsertPoint(mMerge);

	return F;
}

} // namespace MAlice
